/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include "dal_rticonnextdds/converter/QosConverter.hpp"

TEST(ConvertParticipantQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_DomainParticipantQos r_qos, r_qos_stub;
    memcpy(&r_qos_stub, &r_qos, sizeof(DDS_DomainParticipantQos));
    ret = QosConverter::GetInstance()->ConvertParticipantQosFromDalToRtidds(
        DAL_PARTICIPANT_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertPublisherQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_PublisherQos r_qos;
    ret = QosConverter::GetInstance()->ConvertPublisherQosFromDalToRtidds(
        DAL_PUBLISHER_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertSubscriberQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_SubscriberQos r_qos;
    ret = QosConverter::GetInstance()->ConvertSubscriberQosFromDalToRtidds(
        DAL_SUBSCRIBER_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertTopicQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_TopicQos r_qos;
    ret =
        QosConverter::GetInstance()->ConvertTopicQosFromDalToRtidds(DAL_TOPIC_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertDataWriterQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_DataWriterQos r_qos;

    ret = QosConverter::GetInstance()->ConvertDataWriterQosFromDalToRtidds(
        DAL_DATAWRITER_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertDataReaderQosFromDalToRtidds_default, QosConverter)
{
    dal_ret_t ret;
    DDS_DataReaderQos r_qos;

    ret = QosConverter::GetInstance()->ConvertDataReaderQosFromDalToRtidds(
        DAL_DATAREADER_QOS_DEFAULT, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(ConvertParticipantQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_domain_participant_qos_t d_qos = { };
    DDS_DomainParticipantQos r_qos;

    INIT_SEQUENCE(octet, &d_qos.user_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 22);

    d_qos.entity_factory.autoenable_created_entities = DAL_TRUE;
    d_qos.participant_name = "DefinedParticipant";
    d_qos.localhost_only = DAL_TRUE;

    ret = QosConverter::GetInstance()->ConvertParticipantQosFromDalToRtidds(&d_qos, &r_qos);

    EXPECT_EQ(ret, DAL_RETCODE_OK);
    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2] = { };
    // r_qos.user_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.user_data.value, r_value, 2);
    int result = memcmp(r_value, d_value, 2);
    EXPECT_EQ(result, 0);
    EXPECT_EQ(r_qos.entity_factory.autoenable_created_entities, DAL_TRUE);

    EXPECT_STREQ(r_qos.participant_name.name, "DefinedParticipant");
}

TEST(ConvertPublisherQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_publisher_qos_t *d_qos = dal_create_default_publisher_qos();
    DDS_PublisherQos r_qos;

    d_qos->presentation.access_scope = DAL_TOPIC_PRESENTATION_QOS;
    d_qos->presentation.coherent_access = DAL_TRUE;
    d_qos->presentation.ordered_access = DAL_TRUE;
    // TODO: dal_partition_qos_policy_t
    INIT_SEQUENCE(octet, &d_qos->group_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos->group_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos->group_data.value, 22);
    d_qos->entity_factory.autoenable_created_entities = DAL_TRUE;

    ret = QosConverter::GetInstance()->ConvertPublisherQosFromDalToRtidds(d_qos, &r_qos);

    EXPECT_EQ(ret, DAL_RETCODE_OK);
    EXPECT_EQ(r_qos.presentation.access_scope, DDS_TOPIC_PRESENTATION_QOS);
    EXPECT_EQ(r_qos.presentation.coherent_access, DAL_TRUE);
    EXPECT_EQ(r_qos.presentation.ordered_access, DAL_TRUE);

    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2]= { };
    // r_qos.group_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.group_data.value, r_value, 2);
    int result = memcmp(r_value, d_value, 2);
    EXPECT_EQ(result, 0);

    EXPECT_EQ(r_qos.entity_factory.autoenable_created_entities, DAL_TRUE);
    dal_delete_publisher_qos(d_qos);
}

TEST(ConvertSubscriberQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_subscriber_qos_t d_qos;
    memset(&d_qos, 0, sizeof(dal_subscriber_qos_t));    // if d_qos allocate in stack, then must be zero. it's a cave.
    DDS_SubscriberQos r_qos;

    d_qos.presentation.access_scope = DAL_GROUP_PRESENTATION_QOS;
    d_qos.presentation.coherent_access = DAL_TRUE;
    d_qos.presentation.ordered_access = DAL_TRUE;
    // TODO: dal_partition_qos_policy_t
    INIT_SEQUENCE(octet, &d_qos.group_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos.group_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos.group_data.value, 22);
    d_qos.entity_factory.autoenable_created_entities = DAL_TRUE;

    ret = QosConverter::GetInstance()->ConvertSubscriberQosFromDalToRtidds(&d_qos, &r_qos);

    EXPECT_EQ(ret, DAL_RETCODE_OK);
    EXPECT_EQ(r_qos.presentation.access_scope, DDS_GROUP_PRESENTATION_QOS);
    EXPECT_EQ(r_qos.presentation.coherent_access, DAL_TRUE);
    EXPECT_EQ(r_qos.presentation.ordered_access, DAL_TRUE);

    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2] = { };
    // r_qos.group_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.group_data.value, r_value, 2);
    int result = memcmp(r_value, d_value, 2);
    EXPECT_EQ(result, 0);

    EXPECT_EQ(r_qos.entity_factory.autoenable_created_entities, DAL_TRUE);
}

TEST(ConvertTopicQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_topic_qos_t d_qos;
    DDS_TopicQos r_qos;

    INIT_SEQUENCE(octet, &d_qos.topic_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos.topic_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos.topic_data.value, 22);
    d_qos.durability.kind = DAL_TRANSIENT_LOCAL_DURABILITY_QOS;
    d_qos.durability_service.service_cleanup_delay.sec = 111;
    d_qos.durability_service.service_cleanup_delay.nanosec = 222;
    d_qos.durability_service.history_kind = DAL_KEEP_ALL_HISTORY_QOS;
    d_qos.durability_service.history_depth = 111;
    d_qos.durability_service.max_samples = 222;
    d_qos.durability_service.max_instances = 333;
    d_qos.durability_service.max_samples_per_instance = 444;
    d_qos.deadline.period.sec = 555;
    d_qos.deadline.period.nanosec = 666;
    d_qos.latency_budget.duration.sec = 777;
    d_qos.latency_budget.duration.nanosec = 888;
    d_qos.liveliness.kind = DAL_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
    d_qos.liveliness.lease_duration.sec = 111;
    d_qos.liveliness.lease_duration.nanosec = 222;
    d_qos.reliability.kind = DAL_RELIABLE_RELIABILITY_QOS;
    d_qos.reliability.max_blocking_time.sec = 333;
    d_qos.reliability.max_blocking_time.nanosec = 444;
    d_qos.destination_order.kind = DAL_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
    d_qos.history.kind = DAL_KEEP_ALL_HISTORY_QOS;
    d_qos.history.depth = 555;
    d_qos.resource_limits.max_samples = 666;
    d_qos.resource_limits.max_instances = 777;
    d_qos.resource_limits.max_samples_per_instance = 888;
    d_qos.transport_priority.value = 3;
    d_qos.lifespan.duration.sec = 111;
    d_qos.lifespan.duration.nanosec = 222;
    d_qos.ownership.kind = DAL_EXCLUSIVE_OWNERSHIP_QOS;

    ret = QosConverter::GetInstance()->ConvertTopicQosFromDalToRtidds(&d_qos, &r_qos);

    EXPECT_EQ(ret, DAL_RETCODE_OK);

    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2] = { };
    // r_qos.topic_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.topic_data.value, r_value, 2);
    int result = memcmp(r_value, (uint8_t *)d_value, 2);
    EXPECT_EQ(result, 0);

    EXPECT_EQ(r_qos.durability.kind, DDS_TRANSIENT_LOCAL_DURABILITY_QOS);

    EXPECT_EQ(r_qos.durability_service.service_cleanup_delay.sec, 111);
    EXPECT_EQ(r_qos.durability_service.service_cleanup_delay.nanosec, 222);
    EXPECT_EQ(r_qos.durability_service.history_kind, DDS_KEEP_ALL_HISTORY_QOS);
    EXPECT_EQ(r_qos.durability_service.history_depth, 111);
    EXPECT_EQ(r_qos.durability_service.max_samples, 222);
    EXPECT_EQ(r_qos.durability_service.max_instances, 333);
    EXPECT_EQ(r_qos.durability_service.max_samples_per_instance, 444);

    EXPECT_EQ(r_qos.deadline.period.sec, 555);
    EXPECT_EQ(r_qos.deadline.period.nanosec, 666);

    EXPECT_EQ(r_qos.latency_budget.duration.sec, 777);
    EXPECT_EQ(r_qos.latency_budget.duration.nanosec, 888);

    EXPECT_EQ(r_qos.liveliness.kind, DDS_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS);
    EXPECT_EQ(r_qos.liveliness.lease_duration.sec, 111);
    EXPECT_EQ(r_qos.liveliness.lease_duration.nanosec, 222);

    EXPECT_EQ(r_qos.reliability.kind, DDS_RELIABLE_RELIABILITY_QOS);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.sec, 333);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.nanosec, 444);

    EXPECT_EQ(r_qos.destination_order.kind, DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS);

    EXPECT_EQ(r_qos.history.kind, DDS_KEEP_ALL_HISTORY_QOS);
    EXPECT_EQ(r_qos.history.depth, 555);

    EXPECT_EQ(r_qos.resource_limits.max_samples, 666);
    EXPECT_EQ(r_qos.resource_limits.max_instances, 777);
    EXPECT_EQ(r_qos.resource_limits.max_samples_per_instance, 888);

    EXPECT_EQ(r_qos.transport_priority.value, 3);

    EXPECT_EQ(r_qos.lifespan.duration.sec, 111);
    EXPECT_EQ(r_qos.lifespan.duration.nanosec, 222);

    EXPECT_EQ(r_qos.ownership.kind, DDS_EXCLUSIVE_OWNERSHIP_QOS);
}

TEST(ConvertDataWriterQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_datawriter_qos_t d_qos;
    DDS_DataWriterQos r_qos;

    d_qos.durability.kind = DAL_TRANSIENT_LOCAL_DURABILITY_QOS;
    d_qos.durability_service.service_cleanup_delay.sec = 111;
    d_qos.durability_service.service_cleanup_delay.nanosec = 222;
    d_qos.durability_service.history_kind = DAL_KEEP_ALL_HISTORY_QOS;
    d_qos.durability_service.history_depth = 111;
    d_qos.durability_service.max_samples = 222;
    d_qos.durability_service.max_instances = 333;
    d_qos.durability_service.max_samples_per_instance = 444;
    d_qos.deadline.period.sec = 555;
    d_qos.deadline.period.nanosec = 666;
    d_qos.latency_budget.duration.sec = 777;
    d_qos.latency_budget.duration.nanosec = 888;
    d_qos.liveliness.kind = DAL_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
    d_qos.liveliness.lease_duration.sec = 111;
    d_qos.liveliness.lease_duration.nanosec = 222;
    d_qos.reliability.kind = DAL_RELIABLE_RELIABILITY_QOS;
    d_qos.reliability.max_blocking_time.sec = 333;
    d_qos.reliability.max_blocking_time.nanosec = 444;
    d_qos.destination_order.kind = DAL_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
    d_qos.history.kind = DAL_KEEP_ALL_HISTORY_QOS;
    d_qos.history.depth = 555;
    d_qos.resource_limits.max_samples = 666;
    d_qos.resource_limits.max_instances = 777;
    d_qos.resource_limits.max_samples_per_instance = 888;
    d_qos.transport_priority.value = 3;
    d_qos.lifespan.duration.sec = 111;
    d_qos.lifespan.duration.nanosec = 222;
    INIT_SEQUENCE(octet, &d_qos.user_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 22);
    d_qos.ownership.kind = DAL_EXCLUSIVE_OWNERSHIP_QOS;
    d_qos.ownership_strength.value = 4;
    d_qos.writer_data_lifecycle.autodispose_unregistered_instances = 5;

    ret = QosConverter::GetInstance()->ConvertDataWriterQosFromDalToRtidds(&d_qos, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    EXPECT_EQ(r_qos.durability.kind, DDS_TRANSIENT_LOCAL_DURABILITY_QOS);

    EXPECT_EQ(r_qos.durability_service.service_cleanup_delay.sec, 111);
    EXPECT_EQ(r_qos.durability_service.service_cleanup_delay.nanosec, 222);
    EXPECT_EQ(r_qos.durability_service.history_kind, DDS_KEEP_ALL_HISTORY_QOS);
    EXPECT_EQ(r_qos.durability_service.history_depth, 111);
    EXPECT_EQ(r_qos.durability_service.max_samples, 222);
    EXPECT_EQ(r_qos.durability_service.max_instances, 333);
    EXPECT_EQ(r_qos.durability_service.max_samples_per_instance, 444);

    EXPECT_EQ(r_qos.deadline.period.sec, 555);
    EXPECT_EQ(r_qos.deadline.period.nanosec, 666);

    EXPECT_EQ(r_qos.latency_budget.duration.sec, 777);
    EXPECT_EQ(r_qos.latency_budget.duration.nanosec, 888);

    EXPECT_EQ(r_qos.liveliness.kind, DDS_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS);
    EXPECT_EQ(r_qos.liveliness.lease_duration.sec, 111);
    EXPECT_EQ(r_qos.liveliness.lease_duration.nanosec, 222);

    EXPECT_EQ(r_qos.reliability.kind, DDS_RELIABLE_RELIABILITY_QOS);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.sec, 333);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.nanosec, 444);

    EXPECT_EQ(r_qos.destination_order.kind, DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS);

    EXPECT_EQ(r_qos.history.kind, DDS_KEEP_ALL_HISTORY_QOS);
    EXPECT_EQ(r_qos.history.depth, 555);

    EXPECT_EQ(r_qos.resource_limits.max_samples, 666);
    EXPECT_EQ(r_qos.resource_limits.max_instances, 777);
    EXPECT_EQ(r_qos.resource_limits.max_samples_per_instance, 888);

    EXPECT_EQ(r_qos.transport_priority.value, 3);

    EXPECT_EQ(r_qos.lifespan.duration.sec, 111);
    EXPECT_EQ(r_qos.lifespan.duration.nanosec, 222);

    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2] = { };
    // r_qos.user_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.user_data.value, r_value, 2);
    int result = memcmp(r_value, d_value, 2);
    EXPECT_EQ(result, 0);

    EXPECT_EQ(r_qos.ownership.kind, DDS_EXCLUSIVE_OWNERSHIP_QOS);
    EXPECT_EQ(r_qos.ownership_strength.value, 4);

    EXPECT_EQ(r_qos.writer_data_lifecycle.autodispose_unregistered_instances, 5);
}

TEST(ConvertDataReaderQosFromDalToRtidds, QosConverter)
{
    dal_ret_t ret;
    dal_datareader_qos_t d_qos;
    DDS_DataReaderQos r_qos;

    d_qos.durability.kind = DAL_TRANSIENT_LOCAL_DURABILITY_QOS;
    d_qos.deadline.period.sec = 555;
    d_qos.deadline.period.nanosec = 666;
    d_qos.latency_budget.duration.sec = 777;
    d_qos.latency_budget.duration.nanosec = 888;
    d_qos.liveliness.kind = DAL_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
    d_qos.liveliness.lease_duration.sec = 111;
    d_qos.liveliness.lease_duration.nanosec = 222;
    d_qos.reliability.kind = DAL_RELIABLE_RELIABILITY_QOS;
    d_qos.reliability.max_blocking_time.sec = 333;
    d_qos.reliability.max_blocking_time.nanosec = 444;
    d_qos.destination_order.kind = DAL_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
    d_qos.history.kind = DAL_KEEP_ALL_HISTORY_QOS;
    d_qos.history.depth = 555;
    d_qos.resource_limits.max_samples = 666;
    d_qos.resource_limits.max_instances = 777;
    d_qos.resource_limits.max_samples_per_instance = 888;
    INIT_SEQUENCE(octet, &d_qos.user_data.value);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 11);
    PUSH_BACK_SEQUENCE(octet, &d_qos.user_data.value, 22);
    d_qos.ownership.kind = DAL_EXCLUSIVE_OWNERSHIP_QOS;
    d_qos.time_based_filter.minimum_separation.sec = 11;
    d_qos.time_based_filter.minimum_separation.nanosec = 22;
    d_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.sec = 33;
    d_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec = 44;
    d_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.sec = 55;
    d_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.nanosec = 66;

    ret = QosConverter::GetInstance()->ConvertDataReaderQosFromDalToRtidds(&d_qos, &r_qos);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    EXPECT_EQ(r_qos.durability.kind, DDS_TRANSIENT_LOCAL_DURABILITY_QOS);

    EXPECT_EQ(r_qos.deadline.period.sec, 555);
    EXPECT_EQ(r_qos.deadline.period.nanosec, 666);

    EXPECT_EQ(r_qos.latency_budget.duration.sec, 777);
    EXPECT_EQ(r_qos.latency_budget.duration.nanosec, 888);

    EXPECT_EQ(r_qos.liveliness.kind, DDS_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS);
    EXPECT_EQ(r_qos.liveliness.lease_duration.sec, 111);
    EXPECT_EQ(r_qos.liveliness.lease_duration.nanosec, 222);

    EXPECT_EQ(r_qos.reliability.kind, DDS_RELIABLE_RELIABILITY_QOS);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.sec, 333);
    EXPECT_EQ(r_qos.reliability.max_blocking_time.nanosec, 444);

    EXPECT_EQ(r_qos.destination_order.kind, DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS);

    EXPECT_EQ(r_qos.history.kind, DDS_KEEP_ALL_HISTORY_QOS);
    EXPECT_EQ(r_qos.history.depth, 555);

    EXPECT_EQ(r_qos.resource_limits.max_samples, 666);
    EXPECT_EQ(r_qos.resource_limits.max_instances, 777);
    EXPECT_EQ(r_qos.resource_limits.max_samples_per_instance, 888);

    uint8_t d_value[2] = {11, 22};
    uint8_t r_value[2] = { };
    // r_qos.user_data.value.to_array(r_value, 2);
    DDS_OctetSeq_to_array(&r_qos.user_data.value, r_value, 2);
    int result = memcmp(r_value, d_value, 2);
    EXPECT_EQ(result, 0);

    EXPECT_EQ(r_qos.ownership.kind, DDS_EXCLUSIVE_OWNERSHIP_QOS);

    EXPECT_EQ(r_qos.time_based_filter.minimum_separation.sec, 11);
    EXPECT_EQ(r_qos.time_based_filter.minimum_separation.nanosec, 22);

    EXPECT_EQ(r_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.sec, 33);
    EXPECT_EQ(r_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec, 44);
    EXPECT_EQ(r_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.sec, 55);
    EXPECT_EQ(r_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.nanosec, 66);
}
